/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.edu.unal.bioingenium.kbmed.experimentation;

import co.edu.unal.bioingenium.kbmed.config.Configuration;
import co.edu.unal.bioingenium.kbmed.knowledge.KnowledgeSourceMetaData;
import co.edu.unal.bioingenium.kbmed.knowledge.dao.KnowledgeSourceDAO;
import co.edu.unal.bioingenium.kbmed.knowledge.dao.KnowledgeSourceDAOFactory;
import co.edu.unal.bioingenium.kbmed.knowledge.hierarchy.HierarchyService;
import co.edu.unal.bioingenium.kbmed.knowledge.hierarchy.vo.Vertex;
import co.edu.unal.bioingenium.kbmed.knowledge.snomed.SnomedMetaData;
import co.edu.unal.bioingenium.kbmed.util.io.FileManager;
import co.edu.unal.bioingenium.kbmed.util.time.TimeUtil;
import gnu.trove.map.TIntIntMap;
import gnu.trove.map.hash.TIntIntHashMap;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 
 *
 * @author Alejandro Riveros Cruz
 */
public class ConceptDistances {

    private final String startDate;

    public ConceptDistances() {
        startDate = TimeUtil.getCurrentDate();
    }

    public void calculateDistances() {
        KnowledgeSourceDAO knowledgeSourceDAO = KnowledgeSourceDAOFactory.getKnowledgeSourceDAO();
        Set<String> categories = knowledgeSourceDAO.getCategories();
        for (String category : categories) {
            HierarchyService graphManager = HierarchyService.getInstance();
            Set<String> conceptIds = knowledgeSourceDAO.getConceptsInCategory(category);
            Map<Vertex, Number> dijkstraDistanceMap;
            TIntIntMap distancesCount = new TIntIntHashMap();
            Random r = new Random();
            int count = 0;
            Integer currentDistance;
            for (String conceptId : conceptIds) {
                if (r.nextDouble() > 0.9) {
                    System.out.println((count + 1) + " calculating distances for " + conceptId);
                    dijkstraDistanceMap = graphManager.getDijkstraDistanceMap(conceptId, category);
                    count++;
                    for (Vertex vertex : dijkstraDistanceMap.keySet()) {
                        currentDistance = (Integer) dijkstraDistanceMap.get(vertex).intValue();
                        if (distancesCount.containsKey(currentDistance)) {
                            distancesCount.increment(currentDistance);
                        } else {
                            distancesCount.put(currentDistance, 1);
                        }
                    }
                }
            }
            BufferedWriter bufferedWriter = null;
            try {
                String savePath = Configuration.EXPERIMENTS_DIR + File.separator + ConceptDistances.class.getSimpleName() + File.separator + startDate;
                FileManager.verifyAndCreatePath(savePath);
                String categoryStandard = FileManager.getStandardName(category);
                bufferedWriter = new BufferedWriter(new FileWriter(new File(FileManager.toStandardPath(savePath) + Configuration.KNOWLEDGE_SOURCE_NAME + "-" + categoryStandard + "conceptDistances.txt")));
                bufferedWriter.write("Category: " + category + "\n");
                bufferedWriter.write("Vertex: " + graphManager.getHierarchy(category).getDirectedHierarchyGraph().getVertices().size() + "\n");
                bufferedWriter.write("Edges: " + graphManager.getHierarchy(category).getDirectedHierarchyGraph().getEdges().size() + "\n");
                bufferedWriter.write("Sample size: " + count + "\n");
                for (int distanceValue : distancesCount.keys()) {
                    bufferedWriter.write(distanceValue + " - " + distancesCount.get(distanceValue) + "\n");
                    System.out.println(distanceValue + " - " + distancesCount.get(distanceValue));
                }
                bufferedWriter.flush();
                bufferedWriter.close();
                System.out.println("Total concepts selected " + count);
            } catch (IOException ex) {
                Logger.getLogger(ConceptDistances.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    bufferedWriter.close();
                } catch (IOException ex) {
                    Logger.getLogger(ConceptDistances.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

    }

    public static void main(String[] args) {
        ConceptDistances conceptDistances = new ConceptDistances();
        conceptDistances.calculateDistances();
    }
}
